import pymongo
import pandas as pd


# 定期更新视频特征
class updateVideoProfile():

    def __init__(self):
        client = pymongo.MongoClient(host='127.0.0.1', port=27017)
        # 进入数据库（或者创建）
        self.DB = client['movierec']

    # 更新视频特征
    def update_video_profile(self):
        # 拿到视频数据
        videoCollection = self.DB['video']
        videoDf = pd.DataFrame(list(videoCollection.find()))
        video_dataset = videoDf[['bv', 'title', 'tname']]
        # 视频的标签
        tag_dataset = videoDf['tags'].values
        from gensim.corpora import Dictionary
        from gensim.models import TfidfModel
        # 创建字典对象(去重)
        dct = Dictionary(tag_dataset)
        # 统计每一行词频
        corpus = [dct.doc2bow(line) for line in tag_dataset]
        # 训练tf-idf模型
        model = TfidfModel(corpus)
        video_profile = []
        for i, data in enumerate(video_dataset.itertuples()):
            id = data[0]
            bv = data[1]
            title = data[2]
            tname = data[3]
            vector = model[corpus[i]]
            video_tags = sorted(vector, key=lambda x: x[1], reverse=True)[:30]
            topN_tags_weights = dict(map(lambda x: (dct[x[0]], x[1]), video_tags))
            # 要是标签要是当前视频分类，则将权值设为最高1
            topN_tags_weights[tname] = 1
            # 拿到最能代表当前视频的topN tag
            topN_tags = [i for i in topN_tags_weights]
            video_profile.append((bv, title, tname, topN_tags, topN_tags_weights))
        profileDf = pd.DataFrame(video_profile, columns=['bv', 'title', 'tname', 'profile', 'weights'])[
            ["bv", 'tname', 'profile']]
        # 更新视频特征表
        col_video_profile = self.DB['video_profile']
        col_video_profile.drop()
        col_video_profile.insert_many(profileDf.to_dict('records'))

    # 更新标签-视频倒排索引
    def update_inverted_table(self):
        # 拿到视频特征
        col_video_profile = self.DB['video_profile']
        video_profile_df = pd.DataFrame(list(col_video_profile.find()))
        inverted_table = {}
        for index, row in video_profile_df.iterrows():
            for tag in row['profile']:
                _ = inverted_table.get(tag, [])
                _.append(row['bv'])
                inverted_table.setdefault(tag, _)
        res = {}
        for key in inverted_table:
            _1 = res.get('tag', [])
            _1.append(key)
            _2 = res.get('bvs', [])
            _2.append(inverted_table[key])
            res.setdefault('tag', _1)
            res.setdefault('bvs', _2)
        itDf = pd.DataFrame(res)

        # 视频倒排表存入数据库
        video_profile_inverted_table = self.DB['video_profile_inverted_table']
        video_profile_inverted_table.drop()
        video_profile_inverted_table.insert_many(itDf.to_dict('records'))

    # 更新视频相似度
    def update_video_similar(self):
        from gensim.models.doc2vec import Doc2Vec, TaggedDocument
        col_video_profile = self.DB['video_profile']
        video_profile_df = pd.DataFrame(list(col_video_profile.find()))
        video_profile_df.set_index("bv", inplace=True)
        # 将视频的所有的特征取出，使之成为一个文档对象
        documents = [TaggedDocument(words, [bv]) for bv, words in video_profile_df["profile"].iteritems()]
        # 训练一个【文档--向量】模型
        model = Doc2Vec(documents, vector_size=100, window=3, min_count=1, workers=4, epochs=20)
        # 利用模型计算每一篇视频与之最相似的视频
        video_rec_list = []
        for i, data in enumerate(video_profile_df.itertuples()):
            bv = data[0]
            words = video_profile_df["profile"][bv]
            inferred_vector = model.infer_vector(words)
            # 设置成[bv:[bv1,b2,bv3..]]的形式
            row_rec = model.docvecs.most_similar([inferred_vector], topn=20);
            res = [i[0] for i in row_rec]
            res = {'bv': bv, 'rec_list': res}
            video_rec_list.append(res)
        # 视频相似度推荐列表存入数据库
        col_video_simiar_rec = self.DB['video_simiar_rec']
        col_video_simiar_rec.drop()
        col_video_simiar_rec.insert_many(video_rec_list)
